<script setup lang="ts">
import useCategoryStore from "@/store/modules/category.ts";
import { reqAttr, reqDeleteAttr, reqSaveAttr } from "@/api/product/attr";
import { computed, nextTick, onBeforeUnmount, ref, watch } from "vue";
import {
  Attr,
  AttrList,
  AttrResponseData,
  AttrValue,
} from "@/api/product/attr/type.ts";
import { ElMessage } from "element-plus";
import useUserStore from "@/store/modules/user.ts";

// 表格数据
let attrArr = ref<AttrList>([]);
//  使用reactive ,在这里产生了一个问题：明明数据已经更新了，每次显示的都是上一次的数据，而不是最新的数据
// let attrArr = reactive<AttrList>([]);

// 定义场景
let scene = ref<number>(0);

// 引入仓库
let categoryStore = useCategoryStore();

let userStore = useUserStore();

// 保存待提交的平台属性 这属性之前在type中定义过
let attrParams = ref<Attr>({
  attrName: "", // 属性名称
  attrValueList: [], // 属性值列表
  categoryId: "", // 分类id
  categoryLevel: 3, // 分类级别
});

let inputArr = ref<any>([]);

// 获取平台属性列表
const getAttrList = async () => {
  // 立即清空平台属性列表
  attrArr.value = [];

  // 如果没有三级分类id，就不发送请求
  if (!categoryStore.c3Id) {
    return;
  }
  let result: AttrResponseData = await reqAttr(
    categoryStore.c1Id,
    categoryStore.c2Id,
    categoryStore.c3Id,
  );
  if (result.code == 200) {
    attrArr.value = result.data;
  }
};

// 切换场景，显示添加平台属性的card
const addAttrDialogVisible = () => {
  // 切换场景
  scene.value = 1;
  //   收集三级分类id
  attrParams.value.categoryId = categoryStore.c3Id;
};

// 切换场景，显示添加平台属性的card
const updateAttrDialogVisible = (row: Attr) => {
  // 切换场景
  scene.value = 1;
  //   收集三级分类id
  // 这么写是不行的，因为assign方法是浅拷贝，拷贝的是引用，当里面的值改变的时候，外面的值也会改变
  // Object.assign(attrParams.value,row);
  // 使用JSON.parse(JSON.stringify(row))深拷贝  当然也可以使用lodash的深拷贝方法
  Object.assign(attrParams.value, JSON.parse(JSON.stringify(row)));
};

// 提交表单
const submit = async () => {
  // 收集并整理参数
  // 发送请求
  // reqSaveAttr 保存平台属性
  let result = await reqSaveAttr(attrParams.value);
  if (result.code == 200) {
    ElMessage.success(
      attrParams.value.id ? "修改平台属性成功" : "添加平台属性成功",
    );
    // 重新获取平台属性列表
    await getAttrList();
    // 切换场景
    scene.value = 0;
  } else {
    ElMessage.error(
      result.message || attrParams.value.id
        ? "修改平台属性失败"
        : "添加平台属性失败",
    );
  }
  // 重置表单
  resetAttrParams();
};

// 取消表单
const cancel = () => {
  // 切换场景
  scene.value = 0;
  // 重置表单
  resetAttrParams();
};

const resetAttrParams = () => {
  attrParams.value = {
    attrName: "", // 属性名称
    attrValueList: [], // 属性值列表
    categoryId: "", // 分类id
    categoryLevel: 3, // 分类级别
  };
};

// 添加属性值
const addAttrValue = () => {
  // 使用push方法，这个方法会被vue监听到，所以不会出现数据不更新的问题
  attrParams.value.attrValueList.push({
    valueName: "", // 属性值名称
    flag: true, // 是否为编辑状态
  });
  //  让最后一个input获取焦点
  nextTick(() => {
    inputArr.value[inputArr.value.length - 1].focus();
  });
};

// 编辑属性值
const toEdit = (row: AttrValue, $index: number) => {
  // 1.将当前行的flag改为true
  row.flag = true;
  // 2.将当前行的valueName赋值给input
  // 3.让input获取焦点 nextTick是为了保证input已经渲染完毕
  nextTick(() => {
    inputArr.value[$index].focus();
  });
  // 4.让input全选
};

// 查看属性值
const toLook = (row: AttrValue, $index: number) => {
  // 1.判断当前行的valueName是否为空
  if (!row.valueName.trim()) {
    // 删除对应的属性值
    attrParams.value.attrValueList.splice($index, 1);
    ElMessage.warning("属性值不能为空");
    return;
  }
  // 判断  除了自己之外 当前行的valueName是否重复
  let flag = attrParams.value.attrValueList.some(
    //   如果当前行和列表中的某一行的valueName相同，就说明重复了
    (item) => item.valueName == row.valueName && item != row,
  );
  // 如果重复了，就提示用户
  if (flag) {
    // 删除对应的属性值
    attrParams.value.attrValueList.splice($index, 1);
    ElMessage.warning("属性值不能重复");
    return;
  }

  // 将当前行的flag改为false
  row.flag = false;
};

// 删除属性值
const deleteItem = ($index: number) => {
  attrParams.value.attrValueList.splice($index, 1);
};

const deleteAttr = async (row: Attr) => {
  let result = await reqDeleteAttr(row.id);
  if (result.code == 200) {
    ElMessage.success("删除平台属性成功");
    // 重新获取平台属性列表
    await getAttrList();
  } else {
    ElMessage.error("删除平台属性失败");
  }
};

// 监听仓库中的三级分类id变化，如果变化了，就重新获取平台属性列表
watch(
  () => categoryStore.c3Id,
  () => {
    getAttrList();
  },
);

// 计算属性
// attrValueList 的长度为0，返回true，否则返回false
// attrValueList 中的某一项的flag为true，返回true，否则返回false
let committed = computed(() => {
  return (
    attrParams.value.attrValueList.length == 0 ||
    attrParams.value.attrValueList.some((item) => item.flag)
  );
});

// 在组件卸载之前，重置表单，清空store中的所有数据
onBeforeUnmount(() => {
  // 重置表单
  resetAttrParams();
  // 清空store中的所有数据
  categoryStore.$reset();
});

defineOptions({
  name: "Attr",
});
</script>

<template>
  <el-card class="three-selections">
    <Category :scene="scene"></Category>
  </el-card>
  <!--  展示属性页面-->
  <el-card v-if="scene == 0">
    <el-button
      type="primary"
      icon="plus"
      :disabled="!categoryStore.c3Id"
      @click="addAttrDialogVisible"
      class="add-btn"
      >添加平台属性
    </el-button>
    <el-table border :data="attrArr">
      <el-table-column label="序号" type="index" width="80px" align="center">
      </el-table-column>
      <el-table-column label="属性名称" prop="attrName" align="center">
      </el-table-column>
      <el-table-column label="属性值名称" prop="attrValueList" align="center">
        <!--    使用的是默认插槽      -->
        <template #default="{ row }">
          <span v-for="(item, index) in row.attrValueList" :key="index">
            <el-tag size="mini" type="success" style="margin-right: 5px">
              {{ item.valueName }}
            </el-tag>
          </span>
        </template>
      </el-table-column>
      <el-table-column label="操作" align="center">
        <template #default="{ row }">
          <el-button
            type="primary"
            size="mini"
            icon="edit"
            @click="updateAttrDialogVisible(row)"
          ></el-button>

          <el-popconfirm
            :title="`确定删除属性${row.attrName}？`"
            width="250px"
            @confirm="deleteAttr(row)"
          >
            <template #reference>
              <el-button type="danger" size="mini" icon="delete"> </el-button>
            </template>
          </el-popconfirm>
        </template>
      </el-table-column>
    </el-table>
  </el-card>
  <!--  添加属性页面-->
  <el-card v-if="scene == 1">
    <el-form :inline="true">
      <el-form-item label="属性名称">
        <el-input
          placeholder="请输入属性名称"
          v-model="attrParams.attrName"
        ></el-input>
      </el-form-item>
    </el-form>
    <div>
      <!--   没有属性名称的时候。是不允许添加属性值的   -->
      <el-button
        icon="plus"
        type="primary"
        @click="addAttrValue"
        :disabled="!attrParams.attrName"
        >添加属性值</el-button
      >
      <el-button>取消</el-button>
    </div>
    <el-table border class="add-table" :data="attrParams.attrValueList">
      <el-table-column
        align="center"
        label="序号"
        type="index"
        width="80px"
      ></el-table-column>
      <el-table-column label="属性值">
        <!--  row是table中的当前行      -->
        <template #default="{ row, $index }">
          <!--   ref函数会在input组件被创建的时候调用。默认自带参数vc就是input本身       -->
          <el-input
            @blur="toLook(row, $index)"
            v-model="row.valueName"
            placeholder="请你输入属性值"
            v-if="row.flag"
            :ref="(vc: any) => (inputArr[$index] = vc)"
          ></el-input>
          <div v-else @click="toEdit(row, $index)">
            {{ row.valueName }}
          </div>
        </template>
      </el-table-column>
      <el-table-column align="center" label="操作">
        <template #="{ row, $index }">
          <el-button
            type="danger"
            icon="delete"
            @click="deleteItem($index)"
          ></el-button>
        </template>
      </el-table-column>
    </el-table>
    <div>
      <el-button @click="submit" type="primary" :disabled="committed"
        >提交</el-button
      >
      <el-button @click="cancel">取消</el-button>
    </div>
  </el-card>
</template>

<style scoped lang="scss">
.three-selections {
  margin: 20px 0;
}

.add-table {
  margin: 20px 0;
}

.add-btn {
  margin-bottom: 10px;
}
</style>
